package com.rhaggarty.data.type.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * A single, immutable card, as represented by a suit and value.
 * 
 * A card is textually represented by it's ordinal value + a single character representing it's suit (e.g., 10h).
 * 
 * @author Ryan Haggarty (ryanmh@gmail.com)
 *
 */
public final class Card {

    private final Suit suit;
    
    private final Ordinal ordinal;
    
    private static volatile Map<String, Card> cards;

    private static volatile List<Card> orderedCards;
    
    static {
        final Map<String, Card> cardsLocal = new LinkedHashMap<String, Card>(52);
        final List<Card> orderedCardsLocal = new ArrayList<Card>();

        for (final Ordinal ordinal : Ordinal.values()) {
            for (final Suit suit : Suit.values()) {
                final Card card = new Card(suit, ordinal);
                cardsLocal.put(getText(suit, ordinal), card);
                orderedCardsLocal.add(card);
            }
        }
        cards = Collections.unmodifiableMap(cardsLocal);
        orderedCards = Collections.unmodifiableList(orderedCardsLocal);
    }
    
    public static Card getCard(final String value) {
        return cards.get(value);
    }
    
    public static Card getCard(final Ordinal ordinal, final Suit suit) {
        return cards.get(getText(suit, ordinal));
    }

    public static List<Card> getCards() {
        return orderedCards;
    }

    private Card(final Suit suit, final Ordinal ordinal) {
        this.suit = suit;
        this.ordinal = ordinal;
    }
    
    public Suit getSuit() {
        return suit;
    }
    
    public Ordinal getOrdinal() {
        return ordinal;
    }
    
    private static String getText(final Suit suit, final Ordinal ordinal) {
        return ordinal.getText() + suit.getCode();
    }

    @Override
    public String toString() {
        return ordinal.getText() + suit.getCode();
    }
}